import sys
from PyQt4 import QtGui, QtCore
from PyQt4.QtGui import *
from PyQt4.QtCore import Qt 

#
# class to make a widget for the "slaves for sale" poster
# in the slave market
#
class SlavePoster(QWidget):
	def __init__(self, *args, **kw):
		#print "__init__"
		QWidget.__init__(self, *args, **kw)
#
#		we'll want a list of names and a list of cell widgets
#		we could probably use one list of tuples, and eventually
#		we'll need something more complex. but I'll probably
#		manage that at a higher level. This'll do for now.
#
		self.list = []
		self.cells = []
#
#		while we're setting up, define the font we're
#		going to use. 
#
		self.font = QtGui.QFont("Marking Pen", 18)
#
#		start out by putting up the background image
#
#		I probably shouldn't be using fixed geometry here
#		but the one time I tried layout widgets, they clipped
#		the buttons I was trying to place and I gave up on them
#
#		one learning curve at a time, I guess.
#
		path = "resources/poster_blank.png"
		bg = QtGui.QLabel(self)
		bg.setPixmap(QtGui.QPixmap(path))
		bg.setGeometry(0, 0, 219, 295)
#
#		this is the actual table
#		geometry adjusted so as not to obsure the
#		the poster header
#
		self.table = QTableWidget(self)
		self.table.setGeometry(12, 105, 194, 150)
#
#		a bit of spreadsheet to start making the table invisible
#		we need to do the table and the items
#
		ss = """
			QTableWidget {
				border : 0px;
				background-color: transparent;
			}
			QTableWidget:item {
				border : 0px;
				background-color: transparent;
			}
		"""
		self.table.setStyleSheet(ss)
#
#		continuing the process of making the vanilla widget
#		invisible, turn off the grid and hide the column
#		and row headers
#
		self.table.setShowGrid(False)
		self.table.horizontalHeader().hide()
		self.table.verticalHeader().hide()
#
#		more stylesheets, this time to make the scrollbar
#		look like something drawn on paper. 
#
#		this is a big one, so I've defined it at the end
#		of the class rather than have it break up the 
#		flow of logic here
#
		sb = self.table.verticalScrollBar()
		sb.setStyleSheet(SlavePoster.scroll_bar_style)
#
#		set the column: just one, width 180. 
#
		self.table.setColumnCount(1)
		self.table.setColumnWidth(0, 180)
#
#		set a callback for when the cell changes
#		this will let us highlight the current cell
#
		self.table.currentCellChanged.connect(self.cell_changed)
#
#		a "sold out" stamp for when there are no slaves
#
		self.stamp = QLabel(self)
		path = "resources/no_slaves.png"
		self.stamp.setPixmap(QtGui.QPixmap(path))
		self.stamp.setGeometry(-4, 90, 229, 190)

		self.change_cb = None

	def in_stock(self, truth):
		#print "in_stock"
		if truth:
			self.table.show()
			self.stamp.hide()
		else:
			self.table.hide()
			self.stamp.show()

#
#	add a name to the list
#
	def add_name(self, name):
		#print "add_name"
		l = None
#
#		get the index for the new row
#
		idx = len(self.list)
#
#		trying to style the QTableWidgetItem widget is 
#		a right pain. So we use a QLable widget instead
#
#		recycle old cells if possible
#
		if idx < len(self.cells):
			l = self.cells[idx]
			l.show()
		else:
			l = QLabel(self)
			l.setGeometry(0, 0, 194, 40)
			self.cells.append(l)
#
#		set alignment, font, colour , set the name
#
		l.setAlignment(Qt.AlignHCenter|Qt.AlignHCenter)
		l.setFont(self.font)
		l.setStyleSheet("color: black")
		l.setText(name)
#
#		creat a row at that index,
#		set its height, and then set the newly
#		created label as the item for the cell
#
		self.table.insertRow(idx)
		self.table.setRowHeight(idx, 25)
		self.table.setCellWidget(idx, 0, l)
#
#		add the name to our list of names
#		we don't seem to be able to get the cell
#		by the usual methods
#
		self.list.append(name)

	def clear_table(self):
		#print "clear table"
#
#		clear any previous data
#
#		the table widget cells are owned by
#		the table now and will be deleted
#		so long as all other refernces to them
#		are removed. Otherwise they hang around 
#		misplaced on the screen and crash python
#		if you try and access them
#
#		So make sure the cells array gets reset!
#
		self.list = []
		self.cells = []
		self.table.setRowCount(0)
#
#	set the table contents from a list of names
#
	def set_names(self, girls):
		#print "set_names"
		#self.table.currentCellChanged.disconnect(self.cell_changed)
		self.clear_table()
		for g in girls:
			self.add_name(g)
#
#		once done, set the first cell, so the
#		right one is highlighted
#
		self.table.setCurrentCell(0,0)
		#self.table.currentCellChanged.connect(self.cell_changed)

	def down(self):
		#print "down"
		size = self.table.rowCount()
		if size == 0:
			return

		curr = self.table.currentRow()

		curr += 1
		if curr >= size:
			curr = 0
		self.table.setCurrentCell(curr,0)

	def up(self):
		#print "up"
		size = self.table.rowCount()
		if size == 0:
			return

		curr = self.table.currentRow()
		curr -= 1
		if curr < 0:
			curr = size - 1
		self.table.setCurrentCell(curr,0)


#
#	callback from when the current cell changes
#	all we do is reset the text on the new row to 
#	bracket it in "* " and " *", 
#
	def cell_changed(self, cr, cc, pr, rc):
		#print "cell changed"
#
#		if current row == previous row
#		then there's no change and nothing to do
#
		if cr == pr or cr == -1:
			return
#
#		tell the parent widget that the 
#		index has changed
#
		#print "change_cb = ", self.change_cb
		if self.change_cb:
			#print "	calling ..."
			self.change_cb(cr)
#
#		update the ** highlighting
#
		#print ""
		#print "***"
		#print "current row = ", cr
		#print "list length = ", len(self.list)
		name = self.list[cr]
		name = "* " + name + " *"
		self.cells[cr].setText(name)
#
#		if the previous row (pr) is -1
#		we're done
#
		if pr == -1:
			return
#
#		otherwise set the previous cell back to the default
#
		name = self.list[pr]
		self.cells[pr].setText(name)
		

	def set_current(self, index):
		#print "set current"
		self.table.setCurrentCell(index,0)

#
#	honking big style sheet for scroll bars
#
	scroll_bar_style = """
/*
 *		this does the background of the scroll bar
 */
		QScrollBar:vertical {
			border: 2px solid black;
			background: transparent;
			width: 20px;
			margin: 22px 0 22px 0;
		}
/*
 *		this is the bit in the middle that can be dragged
 */
		QScrollBar::handle:vertical {
			border: 1px solid black;
			background: transparent;
			min-height: 20px;
			width: 20px;
		}
/*
 *		these appear to make boxes in the up and down arrow icons
 *		probably you could make them use images. This turns them off
 */
		QScrollBar::add-line:vertical {
			border: 0px solid grey;
			background: transparent;
			height: 15px;
			subcontrol-position: bottom;
			subcontrol-origin: margin;
		}
/*
 *		this is the other one of the above. It's at the top,
 *		so this would have scrolled up
 */
		QScrollBar::sub-line:vertical {
			border: 0px solid grey;
			background: transparent;
			height: 15px;
			subcontrol-position: top;
			subcontrol-origin: margin;
		}
/*
 *		replaced the whole up arrow icon with an image
 */
		QScrollBar::up-arrow:vertical {
			border: 0px solid orange;
			width: 15px;
			height: 10px;
			background-image: url(resources/poster_up.png);
		}
/*
 *		similar for down.
 */
		QScrollBar::down-arrow:vertical {
			border: 0px solid orange;
			width: 15px;
			height: 10px;
			background-image: url(resources/poster_down.png);
		}
/*
 *		don't know what this is. Sounds like it would define a button
 *		to scroll by a page at a time. I'll leave it turned off
 */
		QScrollBar::add-page:vertical, QScrollBar::sub-page:vertical {
			background: none;
		}
	"""



#
# stand alone test code
#
if __name__ == "__main__":
	#from PyQt4.QtCore import *
	#import pdb
#
#	make an app object
#
	app = QtGui.QApplication(sys.argv)
#
#	add the font we're going to use to the font database
#
	font_db = QFontDatabase()
	font_db.addApplicationFont("resources/mark.ttf")
#
#	set up the wood texture as a background, just so we can see
#	how it looks in context
#
	path = "resources/wood.jpg"
	bg = QtGui.QLabel()
	bg.setPixmap(QtGui.QPixmap(path))
	bg.setGeometry(0, 0, 460, 440)
#
#	now make the poster
#
	poster = SlavePoster(bg)
	poster.setGeometry(20, 20, 219, 295)

	names = (
		(
			"Agatha",
			"Bertha",
			"Caroline",
			"Daphne",
			"Edna",
			"Fanny",
			"Gertrude",
		),
		(
			"Hermione",
			"Isolda",
			"Juliet",
		),
		(
			"Kitty",
			"Lucy",
			"Maureen",
			"Nettie"
		)
	)
	index = 0

#
#	set the names
#
	poster.set_names(names[index])
	poster.in_stock(True)

	def next_cb(self):
		#print "next_cb"
		global index 
		#pyqtRemoveInputHook()
		#pdb.set_trace()

		index += 1
		if index >= len(names):
			index = 0
		poster.set_names(names[index])

	next = QPushButton(bg)
	next.setText("Next")
	next.move(20,400)
	next.clicked.connect(next_cb)

#
#	show and run
#
	bg.show()
	sys.exit(app.exec_())

